package net.oschina.allchat.server.framework.pipe.stream.negotiants;

import net.oschina.allchat.message.processing.IProcessingFactory;
import net.oschina.allchat.message.processing.ProcessingService;
import net.oschina.allchat.message.processing.parsers.SimpleObjectParserFactory;
import net.oschina.allchat.message.processing.parsers.core.stanza.IqParserFactory;
import net.oschina.allchat.message.processing.translators.core.stanza.IqTranslatorFactory;
import net.oschina.allchat.protocol.core.JabberId;
import net.oschina.allchat.protocol.core.ProtocolChain;
import net.oschina.allchat.protocol.core.ProtocolException;
import net.oschina.allchat.protocol.core.stanza.Iq;
import net.oschina.allchat.protocol.core.stanza.error.Conflict;
import net.oschina.allchat.protocol.core.stanza.error.Forbidden;
import net.oschina.allchat.protocol.core.stanza.error.NotAuthorized;
import net.oschina.allchat.protocol.core.stream.Session;
import net.oschina.allchat.server.framework.core.integration.IMessage;
import net.oschina.allchat.server.framework.core.session.ISession;
import net.oschina.allchat.server.framework.core.session.ISessionManager;
import net.oschina.allchat.server.framework.pipe.stream.IClientConnectionContext;
import net.oschina.allchat.server.framework.pipe.stream.StreamConstants;

public class SessionEstablishmentNegotiant extends AbstractNegotiant {
	private static IProcessingFactory processingFactory = ProcessingService.createStreamProcessingFactory();
	
	static {
		processingFactory.register(ProtocolChain.first(Iq.PROTOCOL),
				new IqParserFactory()
		);
		processingFactory.register(ProtocolChain.first(Iq.PROTOCOL).next(Session.PROTOCOL),
				new SimpleObjectParserFactory<Session>(
						Session.PROTOCOL,
						Session.class
				)
		);
		
		processingFactory.register(Iq.class, new IqTranslatorFactory());
	}
	
	private ISessionManager sessionManager;
	
	public SessionEstablishmentNegotiant(ISessionManager sessionManager) {
		this.sessionManager = sessionManager;
	}
	
	@Override
	protected boolean doNegotiate(IClientConnectionContext context, IMessage message) {
		Iq request = (Iq)processingFactory.parse((String)message.getPayload());
		
		if (request.getObject() instanceof Session) {
			JabberId jid = (JabberId)context.getAttribute(StreamConstants.KEY_BINDED_CHAT_ID);
			if (jid == null) {
				throw new ProtocolException(new Forbidden());
			}
			
			ISession session = sessionManager.create(jid);
			if (session == null) {
				throw new ProtocolException(new Conflict());
			}
			
			session.setAttribute(StreamConstants.KEY_CLIENT_SESSION_ID, context.getClientSessionId());
			context.setAttribute(StreamConstants.KEY_SESSION_ID, jid);
			
			Iq response = new Iq(Iq.Type.RESULT);
			response.setId(request.getId());
			
			context.write(processingFactory.translate(response));
			
			return true;
		} else {
			throw new ProtocolException(new NotAuthorized());
		}
	}

}
